package com.globant.util.log;

import java.io.File;
import java.sql.Date;
import java.util.Calendar;
import java.util.List;

import org.springframework.dao.DataAccessException;
import org.springframework.dao.RecoverableDataAccessException;

import com.globant.AutomateEMR.FileManager;
import com.globant.util.log.details.ILogDetailsDAO;
import com.globant.util.log.details.LogDetails;
import com.globant.util.log.reports.ILogReportsDAO;
import com.globant.util.log.reports.LogReports;

/**
 * Log functionalities implementation.
 * 
 * @author gonzalo.zarza
 * @version 20130130v1.0
 */

public class LogFunctionsImpl implements ILogFunctions {

	/* 
	================================================================================================
	 Fields
	================================================================================================
	*/
	private ILogDetailsDAO    logDetails;
    private ILogReportsDAO    logReports;
    
	
	/* 
	================================================================================================
	 Methods
	================================================================================================
	*/
    /**
     * Default constructor. Initialises the class fields.
     */
    public LogFunctionsImpl(ILogDetailsDAO logDetails, ILogReportsDAO logReports){        
        this.logDetails     = logDetails;
        this.logReports     = logReports;        
    }
    
    /* ------------------------------------------------------------------------------------------ */
    
	@Override
	public void setLogInformation(File logFile) throws DataAccessException {
	     
		FileManager       fileManager     = new FileManager();
		LogDetails        newLog          = new LogDetails();
		LogReports[]      newReports      = new LogReports[ILogFunctions.REPORTS_NUMBER];		
		// get the data we need
		String            logId           = fileManager.generateLogId(logFile);
		String		      logName		  = logFile.getName();
		long              logSize         = logFile.length();
		String            logStatus       = ILogFunctions.DETAIL_STATUS_STARTING;
		float             logEfficiency   = ILogFunctions.DEFAULT_LOG_EFFICIENCY;
		int               reportStatus    = ILogFunctions.DEFAULT_REPORT_STATUS;		
		
		// save the log info to the log details table
		newLog.setLogId(logId);
        newLog.setName(logName);
        newLog.setSize(logSize);
        newLog.setDateStart(new Date(Calendar.getInstance().getTimeInMillis()));
        newLog.setGeneralStatus(logStatus);
        newLog.setEfficiency(logEfficiency);
		this.logDetails.insertNewLog(newLog);                  // to the db!
		
		// save the reports info to the reports table (there're more than one)
		for (int i = 0; i < ILogFunctions.REPORTS_NUMBER; i++){
		    newReports[i] = new LogReports();
		    newReports[i].setLogId(logId);
		    newReports[i].setReportId(i+1);
		    newReports[i].setStatus(reportStatus);
		    this.logReports.insertNewReport(newReports[i]);    // to the db!
		}
		
	}

	/* ------------------------------------------------------------------------------------------ */
	
	@Override
	public void updateReportStatusInformation(String logId, int reportId, int newStatus) throws DataAccessException {
	    // update the report status
		this.logReports.updateReportStatus(logId, reportId, newStatus);
	}

	/* ------------------------------------------------------------------------------------------ */
	
    @Override
    public void updateLogStatusInformation(String logId, String newStatus) throws DataAccessException {
        // update the log status information
        this.logDetails.updateLogStatus(logId, newStatus);        
    }
	
    /* ------------------------------------------------------------------------------------------ */
    
    @Override
    public void updateEfficiencyInformation() throws DataAccessException {
        // update the efficiency information in the log details table 
        // > using the information obtained from the reports table
        List<String> uniqueIds = this.logDetails.getUniqueLogsId();
        // get reports for the id
        for (String id : uniqueIds){
            this.updateSingleEfficiencyInformation(id);
        }        
    }   
    
	/* ------------------------------------------------------------------------------------------ */
    
    @Override
    public void updateSingleEfficiencyInformation(String logId) throws DataAccessException {
        // check if there's at least one log COMPLETED
        List<LogDetails> details   = this.logDetails.getLogById(logId);
        boolean logCompleted = false;
        for (LogDetails det : details){
            if (det.getGeneralStatus().equals(ILogFunctions.DETAIL_STATUS_COMPLETED)){
                logCompleted = true;
                break;
            }
        }
        // if there's no completed log, we should not update the efficiency information
        if (!logCompleted){
            throw new RecoverableDataAccessException("Unable to update the efficiency information for log_id " + logId + " (no completed log found).");
        }
        
        // update the efficiency information for the given log id        
        List<LogReports> reports   = this.logReports.getReportsByLogId(logId);      
                
        int completed              = 0;
        // get "completed" reports
        for (LogReports rep : reports){
            completed += (rep.getStatus() == ILogFunctions.REPORT_STATUS_COMPLETED) ? 1 : 0;
        }
        // get new efficiency information
        float newEfficiency        = (float) completed / ILogFunctions.REPORTS_NUMBER;        
        // update the efficiency information for the log id
        this.logDetails.updateEfficiency(logId, newEfficiency);        
    }
    
    /* ------------------------------------------------------------------------------------------ */
    
    @Override
    public void deleteLogAndReportsById(String logId) throws DataAccessException {
        // remove reports entries
        this.logReports.deleteReportsByLogId(logId);
        // remove log entry
        this.logDetails.deleteLogById(logId);        
    }
	
}
